/*
 * libsr.h - EnCluster Standard Representation structure and definitions
 * Clunix, cezanne@clunix.com, 2005
 *
 * Copyright (c) 2001-2005 by Clunix Inc. All Rights Reserved.
 */

#ifndef _LIBSR_H_
#define _LIBSR_H_

#include "libbase.h"

#include <stdio.h>


#ifdef __cplusplus
extern "C" {
#endif

typedef struct _sr_t	sr_t;

typedef ecm_uint32	srt_t;

typedef union _sr_val_t {
	ECMBOOL		bval;
	ecm_int32	ival;
	ecm_int64	lval;
	ecm_ptr_t	ptr;
	ecm_double	dval;
	char		*str;
	struct {
		ecm_size_t	size;
		void	*data;
	} oct;
	sr_t		*dir;
} sr_val_t;

typedef int (*sr_printer_t)(srt_t srt, char *buf, ecm_size_t *pbuflen, sr_val_t psrv);
typedef ECMBOOL (*sr_scanner_t)(srt_t srt, char *asrv, sr_val_t *psrv);

typedef struct _sr_parser_t {
	sr_printer_t print;
	sr_scanner_t scan;
} sr_parser_t;

#define SR_BT_NULL	0x000000
#define SR_BT_INT	0x010000
#define SR_BT_LL	0x020000
#define SR_BT_DBL	0x030000
#define SR_BT_STR	0x040000
#define SR_BT_OCT	0x050000
#define SR_BT_DIR	0x060000
#define SR_BT_PTR	0x070000
#define SR_BT_BOOL	0x080000

struct _sr_t;

/* SR apply option */
#define SR_ONE		0x0001	/* only this one */
#define SR_CHILD	0x0002	/* this and children */
#define SR_RECUR	0x0004  /* this and descendants */
#define SR_NO_DEREF	0x0008
#define SR_NOT_THIS	0x0010	/* bit masked with other options;
				 * overrides SR_ONE
				 */
#define SR_CRYPT	0x0011	/* encrypt/decrypt sr using crypto */
#define SR_EXT		0x0012	/* process sr extension field */

/* bits on 0xff000000 is used by sr encoder and decoder and always clear */

/* SR basic representation types */
#define ST_NULL		0x000000
#define ST_INT		0x010000
#define ST_LL		0x020000
#define ST_DBL		0x030000
#define ST_STR		0x040000
#define ST_OCT		0x050000
#define ST_DIR		0x060000
#define ST_PTR		0x070000
#define ST_BOOL		0x080000

#define ST_APPLYOPT	0x010001
#define ST_LNP		0x060001
#define ST_LNI_TYPE	0x010002
#define ST_SRT		0x010003
#define ST_LNPSTR	0x040001


/******************************************************************************
 * SR creation
 ******************************************************************************/
/* create SR */
sr_t *sr_create(srt_t srt);
sr_t *sr_create_ref(srt_t srt);
sr_t *sr_create_HMS(srt_t srt);
sr_t *sr_create_virtual(srt_t srt);
sr_t *sr_create_vHMS(srt_t srt);

#define sr_create_val(type, val)	sr_set_val(sr_create(type), val)
#define sr_create_int(type, ival)	sr_set_int(sr_create(type), ival)
#define sr_create_ll(type, lval)	sr_set_ll(sr_create(type), lval)
#define sr_create_dbl(type, dval)	sr_set_dbl(sr_create(type), dval)
#define sr_create_str(type, str)	sr_set_str(sr_create(type), str)
#define sr_create_oct(type, size, data)	sr_set_oct(sr_create(type), size, data)
#define sr_create_ptr(type, ptr)	sr_set_ptr(sr_create(type), ptr)
#define sr_create_bool(type, bval)	sr_set_bool(sr_create(type), bval)
#define sr_create_dir()			sr_create(ST_DIR)

sr_t *sr_build_virtual(const sr_t *sr);

/* create SR with ASRV */
sr_t *sr_create_asrv(srt_t srt, const char *c_asrv);
#define sr_createn1_asrv(dir, LNP, srt, asrv)	sr_setn1(dir, LNP, sr_create_asrv(srt, asrv))
#define sr_createc_asrv(dir, name, srt, asrv)	sr_setc(dir, name, sr_create_asrv(srt, asrv))

/* create child */
#define sr_createc(root, name, type)	sr_setc(root, name, sr_create(type))
#define sr_createc_val(root, name, type, val)   \
	sr_setc(root, name, sr_create_val(type, val))
#define sr_createc_int(root, name, type, ival)  \
	sr_setc(root, name, sr_create_int(type, ival))
#define sr_createc_ll(root, name, type, lval)   \
	sr_setc(root, name, sr_create_ll(type, lval))
#define sr_createc_dbl(root, name, type, dval)  \
	sr_setc(root, name, sr_create_dbl(type, dval))
#define sr_createc_str(root, name, type, str)   \
	sr_setc(root, name, sr_create_str(type, str))
#define sr_createc_oct(root, name, type, size, data)   \
	sr_setc(root, name, sr_create_oct(type, size, data))
#define sr_createc_bool(root, name, type, bval)   \
	sr_setc(root, name, sr_create_bool(type, bval))
#define sr_createc_dir(root, name) \
	sr_setc(root, name, sr_create_dir())
#define sr_createc_bool(root, name, type, bval)  \
	sr_setc(root, name, sr_create_bool(type, bval))
#define sr_createc_ptr(root, name, type, ptr)	\
	sr_setc(root, name, sr_create_ptr(type, ptr))
#define sr_createc_ref(root, name, type, sr_LNP)	\
	sr_set_ref(sr_setc(root, name, sr_create_ref(type)), sr_LNP)
#define sr_createc_HMS(root, name, type)  sr_setc(root, name, sr_create_HMS(type))

/* create indexed child */
#define sr_createi(dir, idx, type) \
		sr_set_child_idx(dir, idx, sr_create(type))
#define sr_createi_val(dir, idx, type, val) \
		sr_set_idx(dir, idx, sr_create_val(type, val))
#define sr_createi_int(dir, idx, type, ival) \
		sr_set_idx(dir, idx, sr_create_int(type, ival))
#define sr_createi_ll(dir, idx, type, lval) \
		sr_set_idx(dir, idx, sr_create_ll(type, lval))
#define sr_createi_dbl(dir, idx, type, dval) \
		sr_set_idx(dir, idx, sr_create_dbl(type, dval))
#define sr_createi_str(dir, idx, type, str) \
		sr_set_idx(dir, idx, sr_create_str(type, str))
#define sr_createi_oct(dir, idx, type, size, data) \
		sr_set_idx(dir, idx, sr_create_oct(type, size, data))
#define sr_createi_dir(dir, idx) \
		sr_set_idx(dir, idx, sr_create_dir())

/* create descendant */
#define sr_createn1(root, LNP, type)	sr_setn1(root, LNP, sr_create(type))
#define sr_createn1_val(root, LNP, type, val)   \
  sr_setn1(root, LNP, sr_create_val(type, val))
#define sr_createn1_int(root, LNP, type, ival)  \
  sr_setn1(root, LNP, sr_create_int(type, ival))
#define sr_createn1_ll(root, LNP, type, lval)   \
  sr_setn1(root, LNP, sr_create_ll(type, lval))
#define sr_createn1_dbl(root, LNP, type, dval)  \
  sr_setn1(root, LNP, sr_create_dbl(type, dval))
#define sr_createn1_str(root, LNP, type, str)   \
  sr_setn1(root, LNP, sr_create_str(type, str))
#define sr_createn1_oct(root, LNP, type, size, data)   \
  sr_setn1(root, LNP, sr_create_oct(type, size, data))
#define sr_createn1_dir(root, LNP)  sr_setn1(root, LNP, sr_create_dir())
#define sr_createn1_bool(root, LNP, type, bval)  \
	sr_setn1(root, LNP, sr_create_bool(type, bval))
#define sr_createn1_ptr(root, LNP, type, ptr)  \
	sr_setn1(root, LNP, sr_create_ptr(type, ptr))
#define sr_createn1_ref(root, LNP, type, target)  \
	sr_set_ref(sr_setn1(root, LNP, sr_create_ref(type)), target)
#define sr_createn1_HMS(root, LNP, type)  sr_setn1(root, LNP, sr_create_HMS(type))

/******************************************************************************
 * SR duplication
 ******************************************************************************/
/* duplicate SR */
sr_t *sr_dup(const sr_t *sr_src);
#define sr_dupc(sr, name)	sr_dup(sr_getc(sr, name))

/* duplicate indexed child */
#define sr_dupi(dir, idx)		sr_dup(sr_get_idx(dir, idx))

/* duplicate SR value */
sr_val_t sr_dup_val(const srt_t srt, const sr_val_t val);

#define sr_dupn1(sr, LNP)	sr_dup(sr_getn1(sr, LNP))

/******************************************************************************
 * SR copy
 ******************************************************************************/
/* copy SR */
sr_t *sr_cpy(sr_t *sr, const sr_t *sr_src);

/* copy between indexed children */
#define sr_cpyi(dir, idx, src_idx)	sr_set_idx(dir, idx, sr_dup(sr_get_idx(dir, src_idx)))

/* copy SR value */
sr_val_t sr_cpy_val(const sr_t *sr);

/******************************************************************************
 * sr type manipulation
 ******************************************************************************/
/* get SR type */
srt_t sr_get_type(const sr_t *sr);

/* get SR real type */
srt_t sr_get_real_type(const sr_t *sr);

/* get SR base type */
srt_t sr_get_base_type(const sr_t *sr);

/* get SR primitive type */
srt_t sr_get_primitive_type(const sr_t *sr);

/* get member type */
srt_t sr_get_member_type(const sr_t *sr);

#define sr_getc_type(root, name)	sr_get_type(sr_getc(root, name))

/* get descendant type */
#define sr_getn1_type(root, ln)		sr_get_type(sr_getn1(root, ln))

/* get indexed child type */
#define sr_geti_type(dir, idx)		sr_get_type(sr_get_idx(dir, idx))

/* get indexed child base type */
#define sr_geti_base_type(dir, idx)	sr_get_base_type(sr_get_idx(dir, idx))

/* get descendant base type */
#define sr_getn1_base_type(root, ln)	sr_get_base_type(sr_getn1(root, ln))

/* set SR type */
sr_t *sr_set_type(sr_t *sr, srt_t new_srt);

/* set indexed child type */
#define sr_seti_type(dir, idx, new_type)	\
	sr_set_type(sr_get_idx(dir, idx), new_type)

/* check if SR is base type */
ECMBOOL sr_is_base(const sr_t *sr);

/* check if SR is primitive type */
ECMBOOL sr_is_primitive(const sr_t *sr);

/* check if SR is ... */
ECMBOOL sr_is_ref(const sr_t *sr);
ECMBOOL sr_is_HMS(const sr_t *sr);
ECMBOOL sr_is_virtual(const sr_t *sr);
ECMBOOL sr_is_vHMS(const sr_t *sr);
ECMBOOL sr_is_HMSgroup(const sr_t *sr);
ECMBOOL sr_is_realHMSgroup(const sr_t *sr);
ECMBOOL sr_is_real(const sr_t *sr);

/* test if this is dir sr */
ECMBOOL sr_is_group(const sr_t *sr_group);
#define sr_isn1_group(root, ln)	sr_is_group(sr_getn1(root, ln))

sr_t *sr_upcast_vHMS(sr_t *sr_vHMS, srt_t srt);

/******************************************************************************
 * sr name manipulation
 ******************************************************************************/
/* get SR name */
const char *sr_get_name(const sr_t *sr);

/* get indexed child name */
#define sr_geti_name(dir, idx)		sr_get_name(sr_get_idx(dir, idx))

/* get descendant name */
#define sr_getn1_name(root, ln)		sr_get_name(sr_getn1(root, ln))

/* set SR name */
sr_t *sr_set_name(sr_t *sr, const char *new_name);

/******************************************************************************
 * sr value manipulation
 ******************************************************************************/
/* get SR value */
sr_val_t sr_get_val(const sr_t *sr);

/* get indexed child value */
#define sr_geti_val(dir, idx)		sr_get_val(sr_get_idx(dir, idx))
#define sr_cropi_val(dir, idx)		sr_crop_val(sr_get_idx(dir, idx))

/* set SR value */
sr_t *sr_set_val(sr_t *sr, sr_val_t val);

/* set copied SR value */
sr_t *sr_setcpy_val(sr_t *sr, sr_val_t val);

/* set child value */
#define sr_setc_val(root, name, val)	sr_set_val(sr_getc(root, name), val)

/* set indexed child value */
#define sr_seti_val(dir, idx, new_pval)		\
	sr_set_val(sr_get_idx(dir, idx), new_pval)

/* get descendant value */
#define sr_getn1_val(root, ln)		sr_get_val(sr_getn1(root, ln))

/* set SR value with ASRV */
sr_t *sr_set_asrv(sr_t *sr, const char *asrv);

/* set child value with ASRV */
#define sr_setc_asrv(sr_dir, name, asrv)	sr_set_asrv(sr_getc(sr_dir, name), asrv)

/******************************************************************************
 * sr data value related
 ******************************************************************************/
/* get SR data value */
ecm_int32 sr_get_int(const sr_t *sr);
ecm_int64 sr_get_ll(const sr_t *sr);
ecm_double sr_get_dbl(const sr_t *sr);
const char *sr_get_str(const sr_t *sr);
char *sr_crop_str(sr_t *sr);
char *sr_dup_str(const sr_t *sr);
ecm_size_t sr_get_oct_size(const sr_t *sr);
ecm_ptr_t sr_get_oct_data(const sr_t *sr);
ecm_ptr_t sr_get_ptr(const sr_t *sr);
ECMBOOL sr_get_bool(const sr_t *sr);

/* get SR reference value */
const sr_t *sr_get_ref(const sr_t *sr);

/* get SR real value */
sr_t *sr_get_virtual(const sr_t *sr);

/* get child typed-value */
#define sr_getc_int(root, name)		sr_get_int(sr_get_child(root, name))
#define sr_getc_ll(root, name)		sr_get_ll(sr_get_child(root, name))
#define sr_getc_dbl(root, name)		sr_get_dbl(sr_get_child(root, name))
#define sr_getc_str(root, name)		sr_get_str(sr_get_child(root, name))
#define sr_cropc_str(root, name)	sr_crop_str(sr_get_child(root, name))
#define sr_dupc_str(root, name)		sr_dup_str(sr_get_child(root, name))
#define sr_getc_oct_size(root, name)	sr_get_oct_size(sr_get_child(root, name))
#define sr_getc_oct_data(root, name)	sr_get_oct_data(sr_get_child(root, name))
#define sr_getc_bool(root, name)	sr_get_bool(sr_get_child(root, name))
#define sr_getc_ref(root, name)		sr_get_ref(sr_get_child(root, name))
#define sr_getc_deref(root, name)	sr_get_deref(sr_get_child(root, name))

/* get indexed child typed-value */
#define sr_geti_int(dir, idx)		sr_get_int(sr_get_idx(dir, idx))
#define sr_geti_ll(dir, idx)		sr_get_ll(sr_get_idx(dir, idx))
#define sr_geti_dbl(dir, idx)		sr_get_dbl(sr_get_idx(dir, idx))
#define sr_geti_str(dir, idx)		sr_get_str(sr_get_idx(dir, idx))
#define sr_cropi_str(dir, idx)		sr_crop_str(sr_get_idx(dir, idx))
#define sr_dupi_str(dir, idx)		sr_dup_str(sr_get_idx(dir, idx))
#define sr_geti_oct_size(dir, idx)	sr_get_oct_size(sr_get_idx(dir, idx))
#define sr_geti_oct_data(dir, idx)	sr_get_oct_data(sr_get_idx(dir, idx))
#define sr_geti_bool(dir, idx)		sr_get_bool(sr_get_idx(dir, idx))
#define sr_geti_ptr(dir, idx)		sr_get_ptr(sr_get_idx(dir, idx))
#define sr_geti_ref(dir, idx)		sr_get_ref(sr_get_idx(dir, idx))

/* get descendant typed-value */
#define sr_getn1_int(root, ln)		sr_get_int(sr_getn1(root, ln))
#define sr_getn1_ll(root, ln)		sr_get_ll(sr_getn1(root, ln))
#define sr_getn1_dbl(root, ln)		sr_get_dbl(sr_getn1(root, ln))
#define sr_getn1_str(root, ln)		sr_get_str(sr_getn1(root, ln))
#define sr_cropn1_str(root, ln)		sr_crop_str(sr_getn1(root, ln))
#define sr_dupn1_str(root, ln)		sr_dup_str(sr_getn1(root, ln))
#define sr_getn1_oct_size(root, ln)	sr_get_oct_size(sr_getn1(root, ln))
#define sr_getn1_oct_data(root, ln)	sr_get_oct_data(sr_getn1(root, ln))
#define sr_getn1_bool(root, ln)		sr_get_bool(sr_getn1(root, ln))

/* set SR typed-value */
sr_t *sr_set_int(sr_t *sr, ecm_int32 ival);
sr_t *sr_set_ll(sr_t *sr, ecm_int64 lval);
sr_t *sr_set_dbl(sr_t *sr, ecm_double dval);
sr_t *sr_set_str(sr_t *sr, const char *str);
sr_t *sr_set_oct(sr_t *sr, ecm_size_t size, ecm_cptr_t data);
sr_t *sr_set_ptr(sr_t *sr, ecm_cptr_t ptr);
sr_t *sr_set_bool(sr_t *sr, ECMBOOL bval);
sr_t *sr_set_ref(sr_t *sr, sr_t *sr_LNP);
sr_t *sr_set_validref(sr_t *sr, sr_t *sr_LNP);
sr_t *sr_set_ref_LNPstr(sr_t *sr, const char *fmt, ...);
sr_t *sr_set_target(sr_t *sr, const sr_t *sr_target);
sr_t *sr_set_virtual(sr_t *sr, const sr_t *sr_real);

/* set child typed-value */
#define sr_setc_int(root, name, ival)  sr_set_int(sr_getc(root, name), ival)
#define sr_setc_ll(root, name, lval)   sr_set_ll(sr_getc(root, name),  lval)
#define sr_setc_dbl(root, name, dval)  sr_set_dbl(sr_getc(root, name), dval)
#define sr_setc_str(root, name, str)   sr_set_str(sr_getc(root, name), str)
#define sr_setc_bool(root, name, bval)   sr_set_bool(sr_getc(root, name), bval)
#define sr_setc_oct(root, name, size, data)  \
  sr_set_oct(sr_getc(root, name), size, data)
#define sr_setc_ref(root, name, sr_LNP)	sr_set_ref(sr_getc(root, name), sr_LNP)
#define sr_setc_target(root, name, sr_target)	sr_set_target(sr_getc(root, name), sr_target)

/* set indexed child typed-value */
#define sr_seti_int(dir, idx, ival)  sr_set_int(sr_get_idx(dir, idx), ival)
#define sr_seti_ll(dir, idx, lval)   sr_set_ll(sr_get_idx(dir, idx),  lval)
#define sr_seti_dbl(dir, idx, dval)  sr_set_dbl(sr_get_idx(dir, idx), dval)
#define sr_seti_str(dir, idx, str)   sr_set_str(sr_get_idx(dir, idx), str)   
#define sr_seti_oct(dir, idx, size, data)  \
  sr_set_oct(sr_get_idx(dir, idx), size, data)
#define sr_seti_bool(dir, idx, bval)  sr_set_bool(sr_get_idx(dir, idx), bval)

#define sr_setn1_int(root, ln, ival)  sr_set_int(sr_getn1(root, ln), ival)
#define sr_setn1_ll(root, ln, lval)   sr_set_ll(sr_getn1(root, ln),  lval)
#define sr_setn1_dbl(root, ln, dval)  sr_set_dbl(sr_getn1(root, ln), dval)
#define sr_setn1_str(root, ln, str)   sr_set_str(sr_getn1(root, ln), str)
#define sr_setn1_bool(root, ln, bval)   sr_set_bool(sr_getn1(root, ln), bval)

/******************************************************************************
 * sr extension manipulation
 ******************************************************************************/
/* get SR extension */
sr_t *sr_get_ext(const sr_t *sr);
#define sr_geti_ext(dir, idx)		sr_get_ext(sr_get_idx(dir, idx))
#define sr_getn1_ext(root, ln)		sr_get_ext(sr_getn1(root, ln))

/* set SR extension */
sr_t *sr_set_ext(sr_t *sr, sr_t *sr_ext);
#define sr_seti_ext(dir, idx, sr_ext)	sr_set_ext(sr_get_idx(dir, idx), sr_ext)

/******************************************************************************
 * SR accessibility
 ******************************************************************************/
/* get child */
#define sr_getc(dir, name)	sr_get_child(dir, name)
sr_t *sr_get_child(const sr_t *sr_group, const char *name);

/* get indexed child */
sr_t *sr_get_idx(const sr_t *sr_group, int idx);
#define sr_geti(dir, idx)		sr_get_idx(dir, idx)

/* get descendant */
sr_t *sr_get(const sr_t *sr, const sr_t *sr_LNP);
sr_t *sr_get1(const sr_t *sr, const sr_t *sr_LNP);
sr_t *sr_getn(const sr_t *sr, const char *LNP);
sr_t *sr_getn1(const sr_t *sr, const char *LNP);
sr_t *sr_getf(sr_t *root, char *format, ...);

/* get parent */
sr_t *sr_get_parent(const sr_t *sr);

/* get root */
sr_t *sr_get_root(const sr_t *sr);

#define sr_get_first(sr_group)	sr_get_idx(sr_group, 0)
#define sr_first(dir)  sr_get_first(dir)

#define sr_get_last(sr_group)	sr_get_idx(sr_group, -1)
#define sr_last(dir)  sr_get_last(dir)

sr_t *sr_get_next(const sr_t *sr);
#define sr_next(dir)  sr_get_next(dir)
sr_t *sr_get_prev(const sr_t *sr);
#define sr_prev(dir)  sr_get_prev(dir)

/* check if SR is root */
ECMBOOL sr_is_root(const sr_t *sr);
ECMBOOL sr_is_descendant(const sr_t *sr, const sr_t *sr_descendant);

/******************************************************************************
 * SR destruction
 ******************************************************************************/
/* free SR */
void sr_free(sr_t *sr);

/* free child */
#define sr_freec(dir, name)	sr_free(sr_getc(dir, name))

/* free all children */
void sr_clear_child(sr_t *sr_dir);

/* free indexed child */
#define sr_freei(dir, idx)	sr_free(sr_geti(dir, idx))

/* free first child */
#define sr_free_first(dir)	sr_free(sr_geti(dir, 0))

/* free last child */
#define sr_free_last(dir)	sr_free(sr_geti(dir, -1))

/* free value */
void srv_free(srt_t srt, sr_val_t val);

/******************************************************************************
 * SR assignment
 ******************************************************************************/
/* set SR */
sr_t *sr_let(sr_t *sr, sr_t *sr_src);

/* set child */
sr_t *sr_set_child(sr_t *sr_group, const char *name, sr_t *sr_child);

#define sr_setc(sr_group, name, sr_child)	sr_set_child(sr_group, name, sr_child)
#define sr_setn1(sr_group, LNP, sr)	sr_let(sr_getn1(sr_group, LNP), sr)

/* set indexed child */
sr_t *sr_set_idx(sr_t *sr_group, int idx, sr_t *sr_child);
#define sr_seti(sr_group, idx, sr)		sr_set_idx(sr_group, idx, sr)

ECMBOOL sr_is_compatible(const sr_t *sr, const sr_t *sr_compared);
ECMBOOL sr_is_same(const sr_t *sr1, const sr_t *sr2);

/******************************************************************************
 * SR inheritance
 ******************************************************************************/
ECMBOOL sr_is_inherited(const sr_t *sr, srt_t srt_super);
sr_t *srt_get_inherited_srts(const srt_t srt_super);
const srt_t *srt_get_super_srts(srt_t srt);

ECMBOOL srt_is_inherited(const srt_t srt_this, const srt_t srt_super);
srt_t srt_get_common_super(srt_t srt1, srt_t srt2);

/******************************************************************************
 * SR reference operation
 ******************************************************************************/
sr_t *sr_get_deref(const sr_t *sr);
ECMBOOL sr_is_valid_ref(const sr_t *sr);

/******************************************************************************
 * SR octal operation
 ******************************************************************************/
void sr_detach_oct(sr_t *sr);

/******************************************************************************
 * insert operation
 ******************************************************************************/
sr_t *sr_add_idx(sr_t *sr_group, int idx, sr_t *sr_mbr);
sr_t *sr_add_child(sr_t *sr_group, const char *name, sr_t *sr_child);
sr_t *sr_append_unique(sr_t *sr_group, sr_t *sr_mbr);
sr_t *sr_insert(sr_t *sr_sib, sr_t *sr, ECMBOOL ahead);
#define sr_add_first(group, mbr)	sr_add_idx(group, 0, mbr)
#define sr_add_last(group, mbr)		sr_add_idx(group, -1, mbr)
#define sr_append(group, mbr)		sr_add_last(group, mbr)
#define sr_addc(group, name, mbr)	sr_add_child(group, name, mbr)
#define sr_addi(group, idx, mbr)	sr_add_idx(group, idx, mbr)

/******************************************************************************
 * cropping operation
 ******************************************************************************/
/* crop SR */
sr_t *sr_crop(sr_t *sr);

/* crop child */
#define sr_cropc(group, name)		sr_crop(sr_getc(group, name))
#define sr_cropi(group, idx)		sr_crop(sr_geti(group, idx))
#define sr_crop_first(group)		sr_cropi(group, 0)
#define sr_crop_last(group)		sr_cropi(group, -1)

/* crop SR value */
sr_val_t sr_crop_val(sr_t *sr);

/******************************************************************************
 * group operation
 ******************************************************************************/
int sr_get_num_child(const sr_t *sr_group);
ECMBOOL sr_is_empty_group(const sr_t *sr_group);

void sr_merge(sr_t *sr_group, sr_t *sr_merged);
void sr_merge_unique(sr_t *sr_group, sr_t *sr_merged);

/* sorting children */
void sr_sort(sr_t *sr_dir, int apply_opt);      /* ascending order */
void sr_sort_rev(sr_t *sr_dir, int apply_opt);  /* descending order */

ECMBOOL sr_mightbe_member(const sr_t *sr_group, const sr_t *sr_mbr);

ECMBOOL sr_exist(const sr_t *sr_group, const char *name);

/******************************************************************************
 * SR fancy print
 ******************************************************************************/
void sr_fancy_print(FILE *fp, sr_t *sr, int apply_opt, const char *prefix);

/******************************************************************************
 * ASR(SR-ARG) style print and scan
 ******************************************************************************/
sr_t *sr_asr_scan(char *asr);
sr_t *sr_casr_scan(const char *casr);
int sr_asr_asprint(char **pbuf, const sr_t *sr);
int sr_asr_sprint(char *buf, const sr_t *sr);
ecm_size_t sr_asr_sizeof(const sr_t *sr);

ECMBOOL sr_asrv_scan(char *asrv, srt_t srt, sr_val_t *psrv);
ECMBOOL sr_casrv_scan(const char *asrv, srt_t srt, sr_val_t *psrv);
ECMBOOL sr_casri_scan(const char *asrv, srt_t srt, ecm_int32 *pival);
int sr_asrv_asprint(char **pbuf, srt_t srt, sr_val_t srv);
int sr_asrv_sprint(char *buf, srt_t srt, sr_val_t srv);
ecm_size_t sr_asrv_sizeof(srt_t srt, sr_val_t srv);

char *sr_get_asrv(const sr_t *sr);

/******************************************************************************
 * SR encoding/decoding
 ******************************************************************************/
typedef ECMBOOL (*sr_enchook_t)(const sr_t *);
typedef void *sr_enc_ctx_t;
typedef void *sr_dec_ctx_t;

ecm_size_t sr_encode(char **pbuf, const sr_t *sr, sr_enchook_t, int apply_opt);
ECMBOOL sr_decode(const char *enc_buf, ecm_size_t *pbuflen, sr_t **sr_ptr_ret);

sr_enc_ctx_t sr_encode_init(const sr_t *sr_root, sr_enchook_t enchooker, int applyopt);
void sr_encode_done(sr_enc_ctx_t sr_enc_ctx);
ECMBOOL sr_encode_ex(char *buf, ecm_uint32 *pbuflen, sr_enc_ctx_t ctx);

sr_dec_ctx_t sr_decode_init(void);
sr_t *sr_decode_done(sr_dec_ctx_t sr_dec_ctx);
ECMBOOL sr_decode_ex(const char *enc_buf, ecm_size_t *pbuflen, sr_dec_ctx_t ctx);

ecm_size_t sr_encode_val(char *buf, ecm_size_t buflen, srt_t srt, sr_val_t val);
ecm_size_t sr_decode_val(const char *buf, ecm_size_t buflen, srt_t srt, sr_val_t *pval);

ECMBOOL sr_read_enc_sr(int fd, sr_t **psr_res, ecm_size_t bufsize);
ECMBOOL sr_write_enc_sr(int fd, const sr_t *sr_enc, ecm_size_t bufsize);

sr_t *sr_encode_to_oct(const sr_t *sr);
sr_t *sr_decode_from_oct(const sr_t *sr_oct);

/******************************************************************************
 * SR type extension
 ******************************************************************************/
/* Extend SR type */
srt_t sr_type_add(srt_t bt, const char *name, sr_t *sr_supers, sr_parser_t *parser);
srt_t sr_dirtype_add(const char *name, sr_t *sr_supers, sr_parser_t *parser, srt_t srt);
srt_t sr_enumtype_add(const char *name, const char **enumstrs, ECMBOOL bitwise, srt_t srt, srt_t srt_super);

/* Reduce SR type */
ECMBOOL sr_type_remove(srt_t srt);

/******************************************************************************
 * SR typed-value
 ******************************************************************************/
/* build primitive typed-value */
sr_val_t sr_val_int(ecm_int32 ival);
sr_val_t sr_val_ll(ecm_int64 lval);
sr_val_t sr_val_dbl(ecm_double dval);
sr_val_t sr_val_str(char *str);
sr_val_t sr_val_oct(ecm_size_t size, void *data);
sr_val_t sr_val_ptr(ecm_cptr_t ptr);
sr_val_t sr_val_dir(const sr_t *sr_dir);
sr_val_t sr_val_bool(ECMBOOL bval);

/******************************************************************************
 * SR Comparison
 ******************************************************************************/
/* compare values of sr */
int sr_cmp_val(const sr_t *sr_1, const sr_t *sr_2);

/* compare value of sr with ASRV */
int sr_cmp_asrv(sr_t *sr, const char *asrv);

/* compare value */
int srv_cmp(srt_t srt, sr_val_t a, sr_val_t b);

/* compare value with ASRV */
int srv_cmp_asrv(srt_t srt, sr_val_t srv, const char *asrv);

/******************************************************************************
 * srt related
 ******************************************************************************/
const char *srt_get_name(srt_t srt);
ECMBOOL sr_search_srt(const char *srtstr, srt_t *psrt);

srt_t srt_get_base_type(srt_t srt);
srt_t srt_get_primitive_type(srt_t srt);
srt_t srt_get_member_type(srt_t srt);
srt_t srt_get_HMS_type(srt_t srt);
srt_t srt_get_vHMS_type(srt_t srt);
srt_t srt_get_real_type(srt_t srt);
srt_t srt_get_ref_type(const srt_t srt);
srt_t srt_get_target_type(const srt_t srt);

int srt_get_enum_count(const srt_t srt);
int srt_get_bitwise_count(const srt_t srt);

/* check if srt is ... */
ECMBOOL srt_is_group(srt_t srt);
ECMBOOL srt_is_HMS(srt_t srt);
ECMBOOL srt_is_virtual(srt_t srt);
ECMBOOL srt_is_vHMS(srt_t srt);
ECMBOOL srt_is_HMSgroup(srt_t srt);
ECMBOOL srt_is_real(srt_t srt);
ECMBOOL srt_is_null_target(srt_t srt);
ECMBOOL srt_is_valid_target(srt_t srt, srt_t srt_target);
ECMBOOL srt_is_ref(srt_t srt);
ECMBOOL srt_is_enum(srt_t srt);
ECMBOOL srt_is_bitwise(srt_t srt);
ECMBOOL srt_is_base(srt_t srt);
ECMBOOL srt_is_primitive(srt_t srt);
ECMBOOL srt_is_same(srt_t srt1, srt_t srt2);
ECMBOOL srt_is_member(srt_t srt_group, srt_t srt_mbr);
ECMBOOL srt_is_compatible(srt_t srt, srt_t srt_compared);

/******************************************************************************
 * FOREACH
 ******************************************************************************/
#define SR_FOREACH_CHILD(sr, lnp, child)	\
	for (child = (lnp) ? sr_first(sr_getn1(sr, lnp)): sr_first(sr); child; child = sr_next(child))
#define SR_FOREACH_CHILD_N(sr, lnp, child, next)	\
	for (child = (lnp) ? sr_first(sr_getn1(sr, lnp)): sr_first(sr), next = sr_next(child); child; child = next, next = sr_next(child))
#define SR_FOREACH_CHILD_R(sr, lnp, child)	\
	for (child = (lnp) ? sr_last(sr_getn1(sr, lnp)): sr_last(sr); child; child = sr_prev(child))

/******************************************************************************
 * SR tree walk
 ******************************************************************************/
typedef enum {
	SR_WALK_OK,
	SR_WALK_FAILED,
	SR_WALK_PRUNE
} sr_walk_res_t;

typedef sr_walk_res_t (*sr_walk_t)(sr_t **psr, ecm_ptr_t ctx);
typedef sr_walk_res_t (*sr_walkdup_t)(sr_t *sr_dst, sr_t *sr_src, ecm_ptr_t ctx);

ECMBOOL sr_walk(sr_t *sr, sr_walk_t walkfunc, ecm_ptr_t ctx, int opt);
sr_t *sr_walk_dup(sr_t *sr, sr_walkdup_t walkdupfunc, ecm_ptr_t ctx, int opt);

/******************************************************************************
 * LNP related
 ******************************************************************************/
char *sr_get_LNP(const sr_t *sr);
ECMBOOL sr_is_same_sr_LNP(const sr_t *sr_LNP1, const sr_t *sr_LNP2);

/******************************************************************************
 * sr level process creation
 ******************************************************************************/
typedef struct {
	ecm_int32	timeout;
	int		exitcode;
	const char *const*	argv_arr;
	const char *const*	env_arr;
	const char	*workdir;
	sr_t		**psr_in;
	const sr_t	*sr_out;
	const char	*username;
	const char	*passwd;
} sr_exectx_t;

void sr_init_exectx(sr_exectx_t *pctx);
void sr_clear_exectx(sr_exectx_t *pctx);
ecm_err_t sr_exec_process(sr_exectx_t *pctx);
sr_t *sr_read_input(void);
ECMBOOL sr_write_output(sr_t *);

#ifdef __cplusplus
}
#endif

#endif
